package com.yunchao.bank.main.data.repository

import android.app.Application
import android.content.Intent
import com.google.gson.Gson
import com.yunchao.bank.business.data.mapper.toDomainModel
import com.yunchao.bank.business.data.model.BusinessIssueInfoApiModel
import com.yunchao.bank.business.domain.model.BusinessInfoModel
import com.yunchao.bank.configure.data.dao.ConfigureDao
import com.yunchao.bank.main.domain.repository.NavHostRepository
import com.yunchao.library.lock.DeviceHelper
import com.yunchao.library.lock.IDeviceHelper
import com.yunchao.library.socket.*
import com.yunchao.library.socket.config.*
import com.yunchao.library.socket.enum.TransportType
import com.yunchao.library.socket.extensions.hexString
import com.yunchao.library.socket.model.power.PowerManagement
import com.yunchao.library.socket.model.security.*
import com.yunchao.library.socket.utils.ConvertUtils
import com.yunchao.library.socket.utils.ConvertUtils.hexStringToByteArray
import com.yunchao.library.socket.utils.EncryptUtils
import kotlinx.coroutines.*
import java.nio.ByteBuffer
import com.yunchao.bank.main.data.model.DispatchTaskEntity.Companion.STATUS_EXECUTING
import com.yunchao.bank.main.data.model.MetadataUserModel
import com.yunchao.bank.main.domain.repository.SocketErrorMessage
import com.yunchao.library.socket.model.card.CommandData
import com.yunchao.library.socket.model.error.ErrorFeedback
import com.yunchao.library.socket.model.metadata.MetadataEntity
import com.yunchao.library.socket.model.security.DataExchange.Companion.HANDLER_ID
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import timber.log.Timber
import java.nio.charset.Charset

/**
 * NavHostRepository 实现类
 * 负责设备管理和TCP通信的核心实现
 *
 * @param deviceHelper 设备操作辅助类
 * @param application 应用上下文
 * @param dispatchTaskDatasource 任务数据源
 */
internal class NavHostRepositoryImpl(
    private val deviceHelper: DeviceHelper,
    private val application: Application,
    private val configureDao: ConfigureDao,
    private val gson: Gson,
    private val dispatchTaskDatasource: DispatchTaskDatasource
) : NavHostRepository {

    // TCP客户端和安全会话
    private var securitySession: SecuritySession? = null

    private var metadataEntity: MetadataEntity? = null

    private val _socketErrorFlow = MutableSharedFlow<SocketErrorMessage>(extraBufferCapacity = 1)
    private val _businessInfoFlow = MutableSharedFlow<BusinessInfoModel>(extraBufferCapacity = 1)

    // 常量定义
    companion object {
        private const val DEVICE_ID = "YC-SeuicPDA-120"  // 设备ID
        private const val SET_TIME_ACTION = "com.seuic.settings.SETTIME_ACTION" // 时间设置广播
    }

    // region [设备操作]
    /**
     * 打开设备
     * @return 操作结果
     */
    override suspend fun openDevice(): Result<Boolean> = runCatching {
        val result = deviceHelper.openDevice()
        result
    }

    /**
     * 关闭设备
     */
    override suspend fun closeDevice() {
        deviceHelper.closeDevice()
    }
    // endregion

    /**
     * 处理消息加密逻辑
     * @param header 消息头
     * @param bytes 原始字节数组
     * @return 处理后的字节数组
     */
    override suspend fun processEncryption(header: MessageHeader, bytes: ByteArray): ByteArray {
        return withContext(Dispatchers.Default) {
            securitySession?.takeIf { header.isPacket == 1 }?.let { session ->
                when (session.type) {
                    SecuritySession.TYPE_TDES_CBC ->
                        EncryptUtils.encrypt3DES(bytes, session.getKey())

                    else ->
                        EncryptUtils.encrypt3DES(bytes, session.getSKey())?.let { encrypted ->
                            ConvertUtils.byteMergerAll(
                                encrypted,
                                EncryptUtils.calculateMac(encrypted, session.getMKey())
                                    ?: byteArrayOf()
                            )
                        }
                } ?: bytes  // 加密失败返回原始数据
            } ?: bytes  // 无安全会话返回原始数据
        }
    }

    override fun observeSocketError(): Flow<SocketErrorMessage> = _socketErrorFlow.asSharedFlow()


    override fun observeBusinessInfo(): Flow<BusinessInfoModel> = _businessInfoFlow.asSharedFlow()


    override suspend fun handleCardCommand(commandData: CommandData): Result<MetadataUserModel?> =
        runCatching {
            // 1. 获取用户CID
            val userCid = getMetadataUserCid(commandData)
            // 2. 查找匹配用户
            metadataEntity?.userInfoList?.firstOrNull { user ->
                user.cid == userCid &&
                        user.privileges.let {
                            "operate" in it && "audit" in it
                        } == true
            }?.let {
                // 3. 构建结果模型
                MetadataUserModel(
                    isSendCommand = commandData.lpData?.hResult != 0 &&
                            (commandData.wType == 5 || commandData.lpData?.dwEventID == 204),
                    cid = it.cid.orEmpty(),
                    name = it.name.orEmpty(),
                    privileges = it.privileges ?: emptyList(),
                    uid = it.uid ?: -1
                )
            }
        }

    private fun getMetadataUserCid(commandData: CommandData): String? {
        // 1. 快速失败检查
        if (commandData.wType != 4 || commandData.lpData?.hResult != 0) return null

        // 2. 安全处理数据转换
        return commandData.lpData?.lpBuffer?.firstOrNull()?.lpbData
            ?.takeIf { it.isNotEmpty() }
            ?.let { hexStr ->
                runCatching {
                    hexStr.hexStringToByteArray()
                        .toString(Charset.forName("GBK"))
                        .substringBefore("@") // 直接取@前内容
                }.onFailure { Timber.e(it, "CID解析失败") }
                    .getOrNull()
            }
    }

    override suspend fun sendCardCommand(isDelay: Boolean) {
        if (isDelay) {
            delay(1500)
        }
        configureDao.getConfig()?.let {
            CommandSender.sendCommand("192.168.10.80", 51317, "20")
        }
    }


    // region [消息处理]
    /**
     * 处理接收到的消息
     * @param message 接收到的消息
     * @return 协议处理结果
     */
    override suspend fun processIncomingMessage(message: Message): ByteArray? {
        return try {
            val payload = extractPayload(message)
            handleProtocolMessage(message.header, payload)
        } catch (_: Exception) {
            null
        }
    }

    /**
     * 提取消息负载
     * @param message 接收到的消息
     * @return 处理后的消息体字节数组
     */
    private fun extractPayload(message: Message): ByteArray {
        val processedBody = when (val content = message.content) {
            is MessageContent.SingleMessage -> content.data
            is MessageContent.ChunkedMessage -> mergeChunks(content)
        }

        return if (message.header.isPacket == 1) {
            securitySession?.let { session ->
                when (session.type) {
                    SecuritySession.TYPE_TDES_CBC ->
                        EncryptUtils.decrypt3DES(
                            processedBody.copyOfRange(0, processedBody.size - 4),
                            session.getKey()
                        )

                    else ->
                        EncryptUtils.decrypt3DES(
                            processedBody.copyOfRange(0, processedBody.size - 4),
                            session.getSKey()
                        )
                }
            } ?: processedBody
        } else {
            processedBody
        }
    }

    /**
     * 合并分块消息
     * @param chunkedContent 分块消息内容
     * @return 合并后的字节数组
     */
    private fun mergeChunks(chunkedContent: MessageContent.ChunkedMessage): ByteArray {
        require(chunkedContent.chunks.isNotEmpty()) { "分块数据不能为空" }

        val receivedTotalSize = chunkedContent.chunks.sumOf { it.size }
        require(receivedTotalSize == chunkedContent.totalSize) {
            "分块总大小不匹配 (预期: ${chunkedContent.totalSize}, 实际: $receivedTotalSize)"
        }

        return try {
            ByteBuffer.allocateDirect(chunkedContent.totalSize).apply {
                chunkedContent.chunks.forEach { put(it) }
            }.array()
        } finally {
            chunkedContent.chunks.clear() // 确保释放内存
        }
    }
    // endregion

    // region [协议处理器]
    /**
     * 处理协议消息
     * @param header 消息头
     * @param payloads 消息体
     * @return 协议处理结果
     */
    private suspend fun handleProtocolMessage(
        header: MessageHeader,
        payloads: ByteArray
    ): ByteArray? = withContext(Dispatchers.IO) {
        when (header.transport) {
            TransportType.INIT -> handleSocketInit(payloads)
            TransportType.MESSAGE -> handleSocketError(payloads)
            TransportType.CHECK -> handleSocketCheck(payloads)
            TransportType.ACCESS -> handleSocketAccess(payloads)
            TransportType.DISPATCH -> handleSocketDispatch(payloads)
            TransportType.EXECUTE -> handleSocketExecute(payloads)
            TransportType.CONFIRM -> handleSocketConfirm(payloads)
            TransportType.METADATA -> handleSocketMetadata(payloads)
//            TransportType.SUBMIT -> handleSocketSubmit( payloads)
//            TransportType.AUTH -> handleSocketAuth( payloads)
            TransportType.POWER -> handleSocketPower(payloads)
            TransportType.EXCHANGE -> handleSocketExchange(payloads)
            else -> null
        }
    }

    /**
     * 处理初始化
     * @param payload 消息体
     * @return 协议处理结果
     */
    private fun handleSocketInit(
        payload: ByteArray
    ): ByteArray = SocketProtocol.generateDefaultHardwareDescriptor(
        deviceId = DEVICE_ID,
        firmwareVersion = ConvertUtils.lnVToString(payload)
    ).toByteArray()


    private suspend fun handleSocketError(payload: ByteArray): ByteArray? {
        _socketErrorFlow.emit(
            SocketProtocol.createErrorFeedback(payload).let {
                when (it.level) {
                    ErrorFeedback.Level.WARN -> SocketErrorMessage.Warning(it.message)
                    ErrorFeedback.Level.INFO -> SocketErrorMessage.Success(it.message)
                    else -> SocketErrorMessage.Error(it.message)
                }
            }
        )
        return null
    }

    /**
     * 处理环境检查
     * @param payload 消息体
     * @return 协议处理结果
     */
    private suspend fun handleSocketCheck(payload: ByteArray): ByteArray {
        val componentError = SocketProtocol.createEnvironmentCheck(payload).also {
            if (it.error.isNotBlank()) {
                _socketErrorFlow.emit(SocketErrorMessage.Error(it.error))
            }
        }
        return SocketProtocol.createEnvironmentCheckResponse(componentError.error)
    }


    /**
     * 处理接入
     * @param payloads 消息体
     * @return 协议处理结果
     */
    private fun handleSocketAccess(payloads: ByteArray): ByteArray {
        return SocketProtocol.createAccessRequest(payloads).also {
            application.applicationContext.sendBroadcast(
                Intent(SET_TIME_ACTION).apply {
                    setPackage("com.seuic.seuicserver")
                    putExtra("time", it.datetime.toString())
                }
            )
        }.let {
            SocketProtocol.createAccessResponse()
        }
    }


    /**
     * 处理下发任务
     * @param payload 消息体
     * @return 协议处理结果
     */
    private suspend fun handleSocketDispatch(payload: ByteArray): ByteArray {
        return try {
            val request = SocketProtocol.createDispatchRequest(payload)
            val taskId = request.id.toInt()

            val success = dispatchTaskDatasource.saveTask(
                taskId = taskId,
                data = request.data,
                timestamp = request.timestamp.toLong(),
                isOffline = request.isOffline
            )

            val response = if (success) {
                SocketProtocol.createDispatchResponse("")
            } else {
                SocketProtocol.createDispatchResponse("任务${taskId}保存失败")
            }

            response
        } catch (e: Exception) {
            SocketProtocol.createDispatchResponse("任务处理异常: ${e.message}")
        }
    }


    /**
     * 处理执行任务
     * @param payload 消息体
     * @return 协议处理结果
     */
    private suspend fun handleSocketExecute(payload: ByteArray): ByteArray {
        val request = SocketProtocol.createExecuteRequest(payload)
        val taskId = request.id.toInt()
        return try {
            // 尝试更新任务状态并获取结果
            val result = dispatchTaskDatasource.updateTaskStatusAndGetTask(taskId, STATUS_EXECUTING)
            if (result == null) {
                SocketProtocol.createExecuteResponse("任务${taskId}不存在")
            } else {
                if (result.first.status != STATUS_EXECUTING) {
                    return SocketProtocol.createExecuteResponse("任务${taskId}状态更新失败")
                } else {
                    // 成功响应 TODO  要把业务ID 传给业务页面
                    val businessInfoModel =result.second?.let { jsonStr->
                        gson.fromJson(jsonStr, BusinessIssueInfoApiModel::class.java)
                            .toDomainModel(taskId)
                    }
                    businessInfoModel?.let {
                        _businessInfoFlow.emit(it)
                        sendCardCommand()
                        SocketProtocol.createExecuteResponse("")
                    } ?: SocketProtocol.createExecuteResponse("任务${taskId}不存在")
                }
            }
        } catch (e: Exception) {
            SocketProtocol.createExecuteResponse("处理任务${taskId}时发生异常: ${e.message}")
        }
    }


    /**
     * 处理确认任务
     * @param payload 消息体
     * @return 协议处理结果
     */
    private suspend fun handleSocketConfirm(payload: ByteArray): ByteArray {
        val request = SocketProtocol.createConfirmRequest(payload)

        val errorMessage = when {
            request.completeFlags.rejected -> {
                "提交的控制数据未被通讯组件接受"
            }

            request.completeFlags.validationFailed -> {
                "执行前或提交后数据验证失败"
            }

            request.completeFlags.requestDelete -> {
                runCatching {
                    dispatchTaskDatasource.deleteTask(request.id.toInt())
                    "" // 成功删除返回空字符串
                }.getOrElse {
                    "删除任务失败: ${it.message}"
                }
            }

            else -> ""
        }
        // 成功响应
        return SocketProtocol.createConfirmResponse(errorMessage)
    }


    /**
     * 处理元数据
     * @param payload 消息体
     * @return 协议处理结果
     */
    private suspend fun handleSocketMetadata(payload: ByteArray): ByteArray {
        val metadataRequest = SocketProtocol.createMetadataSyncRequest(payload)
        metadataEntity = gson.fromJson(metadataRequest.metadata, MetadataEntity::class.java).also {
            Timber.i("metadata: $it")
            val businessInfoModel = dispatchTaskDatasource.getNextPendingTask()?.let { task ->
                gson.fromJson(task.second, BusinessIssueInfoApiModel::class.java)
                    .toDomainModel(task.first.taskId)
            }
            businessInfoModel?.let {
                _businessInfoFlow.emit(it)
                sendCardCommand()
            }
        }
        return SocketProtocol.createMetadataSyncResponse()
    }

    /**
     * 处理电源管理
     * @param payload 消息体
     * @return 协议处理结果
     */
    private suspend fun handleSocketPower(payload: ByteArray): ByteArray {
        val cmd = SocketProtocol.createPowerManagementPayload(payload)
        return when (cmd.action) {
            PowerManagement.Action.POWER_ON -> getPsamResetResult()
            PowerManagement.Action.POWER_OFF -> PowerManagement.Result.powerOffSuccess()
        }.toByteArray()
    }

    /**
     * 获取 PSAM 重置结果
     * @return 电源管理结果
     */
    private suspend fun getPsamResetResult(): PowerManagement.Result {
        return when (val result = deviceHelper.psamReset()) {
            null -> PowerManagement.Result.failure(IDeviceHelper.PSAM_AUTH_ERROR_MESSAGE)
            else -> when {
                result.startsWith("f1", true) ->
                    PowerManagement.Result.failure(IDeviceHelper.PSAM_AUTH_ERROR_MESSAGE)

                else ->
                    PowerManagement.Result.powerOnSuccess(result.hexStringToByteArray())
            }
        }
    }

    /**
     * 处理数据交换协议
     * @param payload 消息体
     * @return 协议处理结果
     */
    private suspend fun handleSocketExchange(payload: ByteArray): ByteArray {
        val dataExchange = SocketProtocol.createDataExchange(bytes = payload)
        val apduBytes = when {
            dataExchange.cHandler.toInt() == 1 -> handleCHandler1(dataExchange.cApdu)
            else -> handleDefaultExchange(dataExchange)
        }
        return SocketProtocol.createDataExchangeResponse(rApdu = apduBytes)
    }

    /**
     * 处理默认数据交换
     * @param exchange 数据交换对象
     * @return APDU响应字节数组
     */
    private suspend fun handleDefaultExchange(exchange: DataExchange): ByteArray {
        val apduResult = deviceHelper.processedCmdByPSAM(data = exchange.cApdu.hexString)
        val apduBytes = apduResult.hexStringToByteArray()

        if (exchange.rHandler == HANDLER_ID) {
            securitySession = SocketProtocol.createSecuritySession(apduBytes)
        }
        return apduBytes
    }

    /**
     * 处理C处理器1的消息
     * @param apduBytes APDU字节数组
     * @return 处理后的字节数组
     */
    private suspend fun handleCHandler1(apduBytes: ByteArray): ByteArray {
        val autographData = SocketProtocol.createAutographData(
            apduBytes.copyOfRange(5, apduBytes.size)
        )
        return if (autographData.isSubmitData()) {
            handleSubmitData(apduBytes, autographData)
        } else {
            handleControlData(apduBytes, autographData)
        }.let {
            deviceHelper.processedCmdByPSAM(data = it.hexString).hexStringToByteArray()
        }
    }

    /**
     * 处理控制数据
     * @param apduBytes APDU字节数组
     * @param autographData 签名数据
     * @return 处理后的字节数组
     */
    private suspend fun handleControlData(
        apduBytes: ByteArray,
        autographData: AutographData
    ): ByteArray {
        return dispatchTaskDatasource.getTaskData(autographData.id.toInt())?.let {
            val request = SocketProtocol.createSubmitRequest(
                id = autographData.id,
                data = it.second.orEmpty(),
                fragment = autographData.fragment,
                timestamp = it.first.timestamp.toULong()
            )
            val dataBytes = request.toByteArray()
            ConvertUtils.byteMergerAll(apduBytes.copyOfRange(0, 17), dataBytes)
        } ?: byteArrayOf()
    }

    /**
     * 处理提交数据
     * @param apduBytes APDU字节数组
     * @param autographData 签名数据
     * @return 处理后的字节数组
     */
    private suspend fun handleSubmitData(
        apduBytes: ByteArray,
        autographData: AutographData
    ): ByteArray {
        // TODO: 实现提交数据处理逻辑
        return byteArrayOf()
    }
    // endregion
}